import asyncio
import datetime
from typing import Callable, Awaitable

class DailyRecorder:
    def __init__(self, hour = 5, minute = 0, second = 0, microsecond = 0):
        self._task = None
        self._callbacks = []
        self._target_hour = hour  # 凌晨5点
        self._target_minute = minute
        self._target_second = second
        self._target_microsecond = microsecond
        date_str = datetime.datetime.now().strftime("%Y-%m-%d")
        year, month, day = date_str.split('-')
        self._current_date = {'year': year, 'month': month, 'day': day}

    def add_callback(self, callback: Callable[[str], Awaitable[None]]):
        """添加异步回调函数"""
        print("addcallback")
        self._callbacks.append(callback)

    async def _notify_callbacks(self, date_str: str):
        """并行执行所有回调"""
        await asyncio.gather(
            *(cb(date_str) for cb in self._callbacks),
            return_exceptions=True
        )

    async def _calculate_delay(self) -> float:
        """计算到下次目标时间的精确秒数"""
        now = datetime.datetime.now()
        next_run = now.replace(
            hour=self._target_hour,
            minute=self._target_minute,
            second=self._target_second,
            microsecond=self._target_microsecond
        )
        if now >= next_run:
            next_run += datetime.timedelta(days=1)
        print(f"距离下一个凌晨{self._target_hour}点{self._target_minute}分{self._target_second}秒还有{(next_run - now).total_seconds()}秒")
        return (next_run - now).total_seconds()

    async def _run_loop(self):
        while True:
            try:
                delay = await self._calculate_delay()
                await asyncio.sleep(delay)
                
                current_date = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M")  # 格式：年-月-日 小时
                year, month, day, hour, minute = current_date.split('-')  # 分割获取各部分
                self._current_date = {'year': year, 'month': month, 'day': day}
                print(f"[{datetime.datetime.now()}] 记录日期: {current_date}")
                await self._notify_callbacks(current_date)
                
            except Exception as e:
                print(f"调度异常: {e}")
                await asyncio.sleep(60)  # 错误冷却

    def start(self):
        """启动定时器"""
        self._task = asyncio.create_task(self._run_loop())

    def get_current_date(self):
        return self._current_date
    
    def get_target_hour(self):
        return self._target_hour
    
    def get_target_minitue(self):
        return self._target_minute

    async def stop(self):
        """停止定时器"""
        if self._task:
            self._task.cancel()
            try:
                await self._task
            except asyncio.CancelledError:
                pass

# main函数使用的例子
async def sample_callback(date: str):
    print(f"执行回调任务，收到日期: {date}")

async def main():
    recorder = DailyRecorder()
    recorder.add_callback(sample_callback)
    recorder.start()
    
    try:
        while True:
            await asyncio.sleep(3600)  # 保持主循环运行
    except KeyboardInterrupt:
        await recorder.stop()

if __name__ == "__main__":
    asyncio.run(main())